﻿using MessageQuque.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using MessageQuque.Common.Base.Model;
using System.Configuration;
using MessageQuque.Common.Base.Business;
using MessageQuque.Common.Base.Task;
using System.IO;

namespace MessageQuque
{
    public class ServerExecutor
    {
        private static object ququeLocker = new object();
        // 定义数据检查Timer
        private static Timer ququeTimer = new Timer();

        private static object scheduleLocker = new object();
        //定义计划任务Timer
        private static Timer scheduleTimer = new Timer();

        // 检查更新锁
        private static int _checkUpdateLock = 0;

        // 检查计划任务锁
        private static int _checkScheduleLock = 0;

        // 缓存实例化接收器对象
        private static Dictionary<string, IReceiver> receiverList = null;

        // 缓存实例化任务对象
        private static Dictionary<string, ITask> taskList = null;

        // 执行间隔
        private static int _interval = ConfigurationManager.AppSettings.Get("interval").CastTo<int>() * 1000;

        // 缓存任务执行时间
        private static Dictionary<string, DateTime> runTaskList = null;

        private static readonly string runTaskListPath = Directory.GetCurrentDirectory() + "\\RunTask.json";

        /// <summary>
        /// 初始化实例对象
        /// </summary>
        static ServerExecutor()
        {
            receiverList = GetReceives();
            taskList = GetTasks();
            runTaskList = GetRunTaskList();
        }

        ~ServerExecutor()
        {
            
        }

        private static Dictionary<string, DateTime> GetRunTaskList()
        {
            if (!File.Exists(runTaskListPath))
            {
                var dict = new Dictionary<string, DateTime>();

                var json = dict.ToJsonSerialize();

                File.AppendAllText(runTaskListPath, json, Encoding.UTF8);

                return dict;
            }

            var reader = File.OpenText(runTaskListPath);
            var text = reader.ReadToEnd();

            reader.Close();

            var result = text.DeserializeFromJson<Dictionary<string, DateTime>>();

            return result;
        }

        public static void Start()
        {
            #region 设置队列Timer属性
            // 循环间隔时间(1分钟)
            ququeTimer.Interval = _interval;
            // 允许Timer执行
            ququeTimer.Enabled = true;
            // 定义回调
            ququeTimer.Elapsed += new ElapsedEventHandler(CheckUpdateTimer_Elapsed);
            // 定义多次循环
            ququeTimer.AutoReset = true;
            #endregion

            #region 设置定时任务队列属性
            // 循环间隔时间(1秒钟)
            scheduleTimer.Interval = 1000;
            // 允许Timer执行
            scheduleTimer.Enabled = true;
            // 定义回调
            scheduleTimer.Elapsed += new ElapsedEventHandler(CheckTaskTimer_Elapsed);
            // 定义多次循环
            scheduleTimer.AutoReset = true;
            #endregion
        }

        public static void Stop()
        {
            ququeTimer.Enabled = false;
            scheduleTimer.Enabled = false;
        }

        /// <summary>
        /// 执行事件
        /// </summary>
        /// <param name="sender">发送者</param>
        /// <param name="e">事件源</param>
        private static void CheckUpdateTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            // 加锁检查更新锁
            lock (ququeLocker)
            {
                if (_checkUpdateLock == 0) _checkUpdateLock = 1;
                else return;
            }
            //具体实现功能的方法
            foreach (var item in receiverList)
            {
                try
                {
                    var receiver = item.Value;
                    receiver.Dequeue();
                }
                catch (Exception ex)
                {
                    Logger.Error(ex.Message, ex);
                }
            }
            // 解锁更新检查锁
            lock (ququeLocker)
            {
                _checkUpdateLock = 0;
            }
        }

        /// <summary>
        /// 执行事件
        /// </summary>
        /// <param name="sender">发送者</param>
        /// <param name="e">事件源</param>
        private static void CheckTaskTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            // 加锁检查更新锁
            lock (scheduleLocker)
            {
                if (_checkScheduleLock == 0) _checkScheduleLock = 1;
                else return;
            }
            //具体实现功能的方法
            foreach (var item in taskList)
            {
                try
                {
                    var key = item.Value.GetType().FullName;
                    var task = item.Value as TaskBase;
                    var now = DateTime.Now;
                    if (runTaskList.ContainsKey(key))
                    {
                        var days = 1;
                        switch (task.PeriodType)
                        { 
                            case PeriodType.Month:
                                days = GetNextMonthDays(runTaskList[key]);
                                break;
                            case PeriodType.Week:
                                days = 7;
                                break;
                            default:
                                days = 1;
                                break;
                        }

                        var newDate = runTaskList[key].AddDays(days);

                        var targetDate = new DateTime(newDate.Year, newDate.Month, newDate.Day, task.Hour, task.Minutes, 0);

                        if (targetDate > now)
                            continue;

                    }
                    
                    task.Process();
                    runTaskList[key] = now;
                    File.WriteAllText(runTaskListPath, runTaskList.ToJsonSerialize(), Encoding.UTF8);
                }
                catch (Exception ex)
                {
                    Logger.Error(ex.Message, ex);
                }
            }

            // 解锁
            lock (scheduleLocker)
            {
                _checkScheduleLock = 0;
            }
        }

        /// <summary>
        /// 获取下个月今天的间隔天数
        /// </summary>
        /// <param name="now"></param>
        /// <returns></returns>
        private static int GetNextMonthDays(DateTime now)
        {
            var nextMonthDate = now.AddMonths(1);
            int days = (nextMonthDate - now).Days;
            return days;
        }

        /// <summary>
        /// 获取接收器列表
        /// </summary>
        /// <returns></returns>
        public static Dictionary<string, IReceiver> GetReceives()
        {
            Dictionary<string, IReceiver> receivers = new Dictionary<string, IReceiver>();

            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
            var modelSections = config.GetSectionGroup("MessageQuque.Model").Sections;
            var bllSections = config.GetSectionGroup("MessageQuque.Business").Sections;
            foreach (ConfigurationSection item in modelSections)
            {
                if (item == null)
                    continue;

                var typeName = item.SectionInformation.Type;
                var modelType = Type.GetType(typeName);

                var receiverType = Type.GetType(string.Format("{0}`1", typeof(Receiver).FullName)).MakeGenericType(modelType);
                var receiverInstance = Activator.CreateInstance(receiverType) as IReceiver;

                var bllSectionInfo = bllSections.Get(item.SectionInformation.Name);
                var bllTypeName = bllSectionInfo.SectionInformation.Type;
                var bllType = Type.GetType(bllTypeName);
                var bllInstance = Activator.CreateInstance(bllType) as IBusiness;

                receiverInstance.SetBusiness(bllInstance);

                receivers.Add(modelType.FullName, receiverInstance);
            }

            return receivers;
        }

        /// <summary>
        /// 获取计划任务处理列表
        /// </summary>
        /// <returns></returns>
        private static Dictionary<string, ITask> GetTasks()
        {
            Dictionary<string, ITask> tasks = new Dictionary<string, ITask>();

            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
            var taskSections = config.GetSectionGroup("MessageQuque.Task").Sections;
            foreach (ConfigurationSection item in taskSections)
            {
                if (item == null)
                    continue;

                var typeName = item.SectionInformation.Type;
                var taskType = Type.GetType(typeName);
                var taskInstance = Activator.CreateInstance(taskType) as ITask;

                tasks.Add(taskType.FullName, taskInstance);
            }

            return tasks;
        }
    }
}
